﻿using System;
using System.Net;
using Microsoft.Phone.Reactive;
using System.IO;
using System.Linq;
using System.Text;
using System.Collections.Generic;

namespace SharePhone.Provider.Authentication {
    public class FormsBasedAuthentication {
        private const string AuthEnvelope = @"<?xml version=""1.0"" encoding=""utf-8""?>
                    <soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
                      <soap:Body>
                        <Login xmlns=""http://schemas.microsoft.com/sharepoint/soap/"">
                          <username>{0}</username>
                          <password>{1}</password>
                        </Login>
                      </soap:Body>
                    </soap:Envelope>";

        public static IObservable<CookieContainer> Authenticate(string server, string username, string password) {
            CookieContainer cookieJar = new CookieContainer();
            Uri authService = new Uri(string.Format("{0}/_vti_bin/authentication.asmx", server));
            HttpWebRequest authRequest = WebRequest.CreateHttp(authService);
            authRequest.CookieContainer = cookieJar;
            authRequest.Headers["SOAPAction"] = "http://schemas.microsoft.com/sharepoint/soap/Login";
            authRequest.ContentType = "text/xml; charset=utf-8";
            authRequest.Method = "POST";            
            return (from request in Observable.FromAsyncPattern<Stream>(authRequest.BeginGetRequestStream, authRequest.EndGetRequestStream)().Do(stream => {
                                                                                                                                                          UTF8Encoding encoding = new UTF8Encoding();
                                                                                                                                                          string envelope = string.Format(AuthEnvelope, username, password);
                                                                                                                                                          byte[] bytes = encoding.GetBytes(envelope);
                                                                                                                                                          stream.Write(bytes, 0, bytes.Length);
                                                                                                                                                          stream.Close();
                                                                                                                                                      })
                     from response in Observable.FromAsyncPattern<WebResponse>(authRequest.BeginGetResponse, authRequest.EndGetResponse)()
                     select HandleResponse(response, authRequest)).ObserveOnDispatcher();            
        }
        
        private static CookieContainer HandleResponse(WebResponse response, HttpWebRequest request) {
            var httpResponse = response as HttpWebResponse;
            if(httpResponse != null && httpResponse.StatusCode == HttpStatusCode.OK){
                return request.CookieContainer;
            }
            return null;
        }
    }
}
